package rkw.gui;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import javax.smartcardio.CardException;

import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import rkw.database.DatabaseService;
import rkw.database.model.AdministratorToken;
import rkw.database.model.Election;
import rkw.database.model.ElectionVoter;
import rkw.database.model.Member;
import rkw.database.model.Node;
import rkw.election.ElectionService;
import rkw.exceptions.ElectionException;
import rkw.manager.ManagerController;
import rkw.utils.BeanProvider;
import core.cards.election.gui.DlgElectionPreview;
import core.cards.election.model.ElectionBackend;
import core.database.NodeType;
import core.exceptions.CommunicationInitiationException;
import core.exceptions.PortInUseException;
import core.smartCardReader.SmartCardReaderService;
import core.smartCardReader.TokenCard;
import core.utils.ConfigPropertiesHolder;
import core.utils.Converter;
import core.utils.Property;

@SuppressWarnings("restriction")
public class MainWindow implements ApplicationContextAware {
	private static class ContentProvider implements IStructuredContentProvider {
		public Object[] getElements(Object inputElement) {
			return new Object[0];
		}

		public void dispose() {
		}

		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		}
	}

	private static final Logger LOGGER = LoggerFactory.getLogger(MainWindow.class);

	public static boolean isInDebugMode() {
		return ConfigPropertiesHolder.getInstance().getProperty(Property.DEBUG_STATE).equalsIgnoreCase("true");
	}

	private SmartCardReaderService smartCardReaderService = BeanProvider.smartCardReaderService();
	private DatabaseService databaseService = BeanProvider.databaseService();
	private ElectionService electionService = BeanProvider.electionService();

	private Member loggedMember;
	private Election loggedElection;

	protected Shell shlMain;
	private static ManagerController manager;
	private ApplicationContext context;

	private StackLayout mainStackLayout;

	private Composite loginCmp;

	private Label loginCmpLblLogin;
	private Label loginCmpLblMember;
	private Text loginCmpTxtMember;
	private Label loginCmpLblElection;
	private Text loginCmpTxtElection;
	private Button loginCmpBtnCheckToken;
	private Button loginCmpBtnLogin;

	private Composite mainCmp;

	private Label lblLoggedAs;
	private Text mainCmpTxtMember;
	private Label lblForElection;
	private Text mainCmpTxtElection;
	private TabFolder tbFldMain;
	private TabItem tbtmElection;
	private TabItem tbtmVoters;
	private Composite cmpElection;

	private Group grpDetails;
	private Text txtElectionDescription;
	private Text txtElectionName;
	private Text txtElectionStartDate;
	private Text txtElectionEndDate;
	private Composite cmpVoters;
	private Table tblVoters;
	private TableViewer tblVwrVoters;
	private TableColumn tblClmnVoterName;
	private TableViewerColumn tblVwrClmnVoterName;
	private TableColumn tblClmnVoterSurname;
	private TableViewerColumn tblVwrClmnVoterSurname;
	private TableColumn tblClmnVoterIdentificationField;
	private TableViewerColumn tblVwrClmnVoterIdentificationField;
	private TableColumn tblClmnVoterSex;
	private TableViewerColumn tblVwrClmnVoterSex;
	private Composite cmpVotersButtons;
	private Button btnVote;
	private TableColumn tblClmnAddress;
	private TableViewerColumn tblVwrClmnVoterAddress;
	private Text txtVoterSearch;
	private TableColumn tblClmnType;
	private TableViewerColumn tblVwrClmnVoterType;
	private TableColumn tblClmnHasVoted;
	private TableViewerColumn tblVwrClmnVoterHasVoted;
	private Button btnCardPreview;
	private Button btnResetToken;
	private Composite cmpButtons;
	private Button btnStartEndElection;
	private Button btnCheckConnection;

	public MainWindow() {
		LOGGER.debug("Tworzę MainWindow");
		LOGGER.debug("Utworzono MainWindow");
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.context = applicationContext;
	}

	public static ManagerController getManager() {
		return manager;
	}

	/**
	 * @wbp.parser.entryPoint Open the window.
	 */
	public void open() {
		final Display display = Display.getDefault();

		manager = context.getBean(ManagerController.class);
		try {
			manager.setUp();
		} catch (CommunicationInitiationException e) {
			e.printStackTrace();
		} catch (PortInUseException e) {
			e.printStackTrace();
		}
		createContents();
		shlMain.open();
		shlMain.layout();

		while (!shlMain.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}

		manager.shutDown();
	}

	public Node askForMainNodeData() {
		Node node = null;
		
		NodeType[] nodeTypes = new NodeType[] { NodeType.RKW };
		Node mainNode = new Node();
		mainNode.setNodeType(NodeType.RKW);

		WzdAddEditNode wzdAddEditNode = new WzdAddEditNode(true, mainNode, nodeTypes);
		WizardDialog wzdDlg = new WizardDialog(shlMain, wzdAddEditNode);
		wzdDlg.open();
		if (wzdDlg.getReturnCode() == IDialogConstants.OK_ID) {
			node = mainNode;
		}
		
		return node;
	}

	/**
	 * Create contents of the window.
	 */
	protected void createContents() {
		createShlMain();

		createLoginCmp();
		createMainCmp();

		mainStackLayout.topControl = loginCmp;
		new Label(loginCmp, SWT.NONE);
	}

	private void createShlMain() {
		shlMain = new Shell();
		shlMain.setMinimumSize(new Point(640, 480));
		shlMain.setSize(1024, 800);
		shlMain.setLocation(5, 5);
		Node mainNode = manager.getMainNode();
		if(mainNode == null) {
			shlMain.setText("Daj Głos - RKW");
		} else {
			shlMain.setText("Daj Głos - RKW: " + mainNode.getName() + "[" + mainNode.getLocatorURI() + "]");
		}

		mainStackLayout = new StackLayout();
		shlMain.setLayout(mainStackLayout);
	}

	private void createLoginCmp() {
		loginCmp = new Composite(shlMain, SWT.NONE);

		GridLayout glLoginCmp = new GridLayout(3, false);
		glLoginCmp.marginTop = 200;
		glLoginCmp.marginRight = 200;
		glLoginCmp.marginLeft = 200;
		loginCmp.setLayout(glLoginCmp);

		loginCmpLblLogin = new Label(loginCmp, SWT.NONE);
		loginCmpLblLogin.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false, 3, 1));
		loginCmpLblLogin.setText("Login");

		loginCmpLblMember = new Label(loginCmp, SWT.NONE);
		loginCmpLblMember.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
		loginCmpLblMember.setText("Member");

		loginCmpTxtMember = new Text(loginCmp, SWT.BORDER);
		loginCmpTxtMember.setEditable(false);
		loginCmpTxtMember.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));

		loginCmpBtnCheckToken = new Button(loginCmp, SWT.NONE);
		loginCmpBtnCheckToken.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				try {
					UUID adminUuid = smartCardReaderService.getFirstAdminToken();
					if (adminUuid == null) {
						MessageDialog.openInformation(shlMain, "Info", "No Admin Token detected.");
					} else {
						AdministratorToken administratorToken = electionService.getAdministratorTokenByValue(adminUuid);
						if (administratorToken == null) {
							loginCmpTxtMember.setText("Not found");
							loginCmpTxtElection.setText("Not found");
						} else {
							Member member = administratorToken.getMember();
							Election election = administratorToken.getElection();
							loginCmpTxtMember.setText(member.toString());
							loginCmpTxtElection.setText(election.getName());
						}
					}
				} catch (CardException e) {
					e.printStackTrace();
				}
			}
		});
		loginCmpBtnCheckToken.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 2));
		loginCmpBtnCheckToken.setText("Check Token");

		loginCmpLblElection = new Label(loginCmp, SWT.NONE);
		loginCmpLblElection.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
		loginCmpLblElection.setText("Election");

		loginCmpTxtElection = new Text(loginCmp, SWT.BORDER);
		loginCmpTxtElection.setEditable(false);
		loginCmpTxtElection.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
		new Label(loginCmp, SWT.NONE);

		loginCmpBtnLogin = new Button(loginCmp, SWT.NONE);
		loginCmpBtnLogin.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				try {
					UUID adminUuid = smartCardReaderService.getFirstAdminToken();
					if (adminUuid == null) {
						MessageDialog.openInformation(shlMain, "Info", "No Admin Token detected.");
					} else {
						AdministratorToken administratorToken = databaseService.getAdministratorTokenByValue(adminUuid.toString());
						if (administratorToken == null) {
							loginCmpTxtMember.setText("Not found");
							loginCmpTxtElection.setText("Not found");
						} else {
							login(administratorToken);
						}
					}

				} catch (CardException e) {
					e.printStackTrace();
				}
			}
		});
		loginCmpBtnLogin.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
		loginCmpBtnLogin.setText("Login");
	}

	protected void login(AdministratorToken administratorToken) {
		loggedMember = administratorToken.getMember();
		loggedElection = administratorToken.getElection();

		initMainCmp();

		mainStackLayout.topControl = mainCmp;
		shlMain.layout();
	}

	protected void logout() {
		loggedMember = null;
		loggedElection = null;

		mainStackLayout.topControl = loginCmp;
		shlMain.layout();
	}

	private void createMainCmp() {
		mainCmp = new Composite(shlMain, SWT.NONE);
		mainCmp.setLayout(new GridLayout(4, false));

		lblLoggedAs = new Label(mainCmp, SWT.NONE);
		lblLoggedAs.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
		lblLoggedAs.setText("Logged as");

		mainCmpTxtMember = new Text(mainCmp, SWT.BORDER);
		GridData gdTxtMember = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
		gdTxtMember.widthHint = 200;
		mainCmpTxtMember.setLayoutData(gdTxtMember);
		mainCmpTxtMember.setEditable(false);

		lblForElection = new Label(mainCmp, SWT.NONE);
		lblForElection.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
		lblForElection.setText("for Election");

		mainCmpTxtElection = new Text(mainCmp, SWT.BORDER);
		mainCmpTxtElection.setEditable(false);
		mainCmpTxtElection.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));

		tbFldMain = new TabFolder(mainCmp, SWT.NONE);
		tbFldMain.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true, 4, 1));

		btnCheckConnection = new Button(mainCmp, SWT.NONE);
		btnCheckConnection.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				DlgCommunicationState dlgCommunicationState = new DlgCommunicationState(shlMain, manager);
				dlgCommunicationState.open();
				dlgCommunicationState = null;
			}
		});
		btnCheckConnection.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 4, 1));
		btnCheckConnection.setText("Check connection");

		createElectionTab();
		createVotersTab();
	}

	private void createElectionTab() {
		tbtmElection = new TabItem(tbFldMain, SWT.NONE);
		tbtmElection.setText("Election");

		cmpElection = new Composite(tbFldMain, SWT.NONE);
		tbtmElection.setControl(cmpElection);
		cmpElection.setLayout(new GridLayout(1, false));

		grpDetails = new Group(cmpElection, SWT.NONE);
		grpDetails.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
		grpDetails.setText("Details");
		grpDetails.setLayout(new GridLayout(3, false));

		new Label(grpDetails, SWT.NONE).setText("Name");

		txtElectionName = new Text(grpDetails, SWT.BORDER);
		txtElectionName.setEditable(false);
		txtElectionName.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));

		new Label(grpDetails, SWT.NONE).setText("Description");

		txtElectionDescription = new Text(grpDetails, SWT.BORDER | SWT.WRAP | SWT.MULTI);
		txtElectionDescription.setEditable(false);
		GridData gdTxtElectionDescription = new GridData(SWT.FILL, SWT.TOP, true, false, 2, 1);
		gdTxtElectionDescription.heightHint = 120;
		txtElectionDescription.setLayoutData(gdTxtElectionDescription);

		new Label(grpDetails, SWT.NONE).setText("Start date");

		txtElectionStartDate = new Text(grpDetails, SWT.BORDER);
		txtElectionStartDate.setEditable(false);
		txtElectionStartDate.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));

		new Label(grpDetails, SWT.NONE).setText("End date");

		txtElectionEndDate = new Text(grpDetails, SWT.BORDER);
		txtElectionEndDate.setEditable(false);
		txtElectionEndDate.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));

		cmpButtons = new Composite(grpDetails, SWT.NONE);
		cmpButtons.setLayout(new GridLayout(3, false));
		cmpButtons.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 3, 1));

		btnCardPreview = new Button(cmpButtons, SWT.NONE);
		btnCardPreview.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				ElectionBackend electionBackend = (ElectionBackend) Converter.xmlToObject(loggedElection.getCards());
				DlgElectionPreview dlgElectionPreview = new DlgElectionPreview(shlMain, electionBackend);
				dlgElectionPreview.open();
			}
		});
		btnCardPreview.setText("Card Preview");

		btnResetToken = new Button(cmpButtons, SWT.NONE);
		btnResetToken.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				List<TokenCard> votingTokenCardList = new ArrayList<TokenCard>();
				try {
					for (TokenCard tokenCard : smartCardReaderService.getInsertedTokenCards()) {
						if (tokenCard.isAdminToken() == false) {
							votingTokenCardList.add(tokenCard);
						}
					}

					if (votingTokenCardList.isEmpty() && MainWindow.isInDebugMode() == false) {
						MessageDialog.openInformation(shlMain, "Info", "No Voting Cards detected.");
					} else {
						if (votingTokenCardList.size() > 1) {
							if (!MessageDialog.openConfirm(shlMain, "Confirm", "Detected more than one Voting Card. Token used will be the first inserted Card. Proceed?")) {
								return;
							}
						}

						UUID uuid = electionService.generateToken();
						if (MainWindow.isInDebugMode() == false) {
							TokenCard selectedTokenCard = votingTokenCardList.get(0);
							selectedTokenCard.clearTokens();
							selectedTokenCard.writeVotingToken(uuid);
						}
						MessageDialog.openInformation(shlMain, "Info", "Voting Token has been succesfully added to the Card.");
					}
				} catch (CardException exception) {
					LOGGER.error(exception.toString());
				}
			}
		});
		btnResetToken.setText("Reset Token");

		btnStartEndElection = new Button(cmpButtons, SWT.NONE);
		btnStartEndElection.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				UUID adminToken;
				try {
					adminToken = smartCardReaderService.getFirstAdminToken();
					if (btnStartEndElection.getText().compareTo("Start Election") == 0) {
						electionService.startElection(adminToken);
						btnStartEndElection.setText("End Election");
					} else {
						electionService.endElection(adminToken);
						btnStartEndElection.setText("End Election");
						btnStartEndElection.setEnabled(false);
					}
				} catch (ElectionException exception) {
					MessageDialog.openError(shlMain, "Start Error", exception.getMessage());
					exception.printStackTrace();
				} catch (CardException exception) {
					exception.printStackTrace();
				}
			}
		});
		btnStartEndElection.setText("Start Election");
	}

	private void createVotersTab() {
		tbtmVoters = new TabItem(tbFldMain, SWT.NONE);
		tbtmVoters.setText("Voters");

		cmpVoters = new Composite(tbFldMain, SWT.NONE);
		tbtmVoters.setControl(cmpVoters);
		cmpVoters.setLayout(new GridLayout(2, false));

		txtVoterSearch = new Text(cmpVoters, SWT.BORDER);
		txtVoterSearch.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent event) {
				tblVwrVoters.setInput(electionService.findElectionVotersLike(loggedElection, txtVoterSearch.getText()));
			}
		});
		txtVoterSearch.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
		txtVoterSearch.setMessage("Type search phrase");

		tblVwrVoters = new TableViewer(cmpVoters, SWT.BORDER | SWT.FULL_SELECTION);
		tblVoters = tblVwrVoters.getTable();
		tblVoters.setHeaderVisible(true);
		GridData gdTblVoters = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1);
		gdTblVoters.widthHint = 700;
		tblVoters.setLayoutData(gdTblVoters);

		tblVwrClmnVoterName = new TableViewerColumn(tblVwrVoters, SWT.NONE);
		tblVwrClmnVoterName.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				return element == null ? "" : ((ElectionVoter) element).getVoter().getName();
			}
		});
		tblClmnVoterName = tblVwrClmnVoterName.getColumn();
		tblClmnVoterName.setWidth(125);
		tblClmnVoterName.setText("Name");

		tblVwrClmnVoterSurname = new TableViewerColumn(tblVwrVoters, SWT.NONE);
		tblVwrClmnVoterSurname.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				return element == null ? "" : ((ElectionVoter) element).getVoter().getSurname();
			}
		});
		tblClmnVoterSurname = tblVwrClmnVoterSurname.getColumn();
		tblClmnVoterSurname.setWidth(190);
		tblClmnVoterSurname.setText("Surname");

		tblVwrClmnVoterType = new TableViewerColumn(tblVwrVoters, SWT.NONE);
		tblVwrClmnVoterType.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				if (element == null) {
					return "";
				}
				ElectionVoter electionVoter = (ElectionVoter) element;
				return electionVoter.getIsNonResident() ? "Non-resident" : "Resident";
			}
		});
		tblClmnType = tblVwrClmnVoterType.getColumn();
		tblClmnType.setWidth(100);
		tblClmnType.setText("Type");

		tblVwrClmnVoterHasVoted = new TableViewerColumn(tblVwrVoters, SWT.NONE);
		tblVwrClmnVoterHasVoted.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				if (element == null) {
					return "";
				}
				ElectionVoter electionVoter = (ElectionVoter) element;
				return electionVoter.getHasVoted() ? "Yes" : "No";
			}
		});
		tblClmnHasVoted = tblVwrClmnVoterHasVoted.getColumn();
		tblClmnHasVoted.setWidth(100);
		tblClmnHasVoted.setText("Has voted?");

		tblVwrClmnVoterIdentificationField = new TableViewerColumn(tblVwrVoters, SWT.NONE);
		tblVwrClmnVoterIdentificationField.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				return element == null ? "" : ((ElectionVoter) element).getVoter().getIdentificationField();
			}
		});
		tblClmnVoterIdentificationField = tblVwrClmnVoterIdentificationField.getColumn();
		tblClmnVoterIdentificationField.setWidth(190);
		tblClmnVoterIdentificationField.setText("Identification field");

		tblVwrClmnVoterSex = new TableViewerColumn(tblVwrVoters, SWT.NONE);
		tblVwrClmnVoterSex.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				return element == null ? "" : ((ElectionVoter) element).getVoter().getSex().toString();
			}
		});
		tblClmnVoterSex = tblVwrClmnVoterSex.getColumn();
		tblClmnVoterSex.setWidth(125);
		tblClmnVoterSex.setText("Sex");

		tblVwrClmnVoterAddress = new TableViewerColumn(tblVwrVoters, SWT.NONE);
		tblVwrClmnVoterAddress.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				return element == null ? "" : ((ElectionVoter) element).getVoter().getAddress();
			}
		});
		tblClmnAddress = tblVwrClmnVoterAddress.getColumn();
		tblClmnAddress.setWidth(250);
		tblClmnAddress.setText("Address");
		tblVwrVoters.setContentProvider(new ContentProvider() {
			@Override
			public Object[] getElements(Object inputElement) {
				@SuppressWarnings("unchecked")
				List<ElectionVoter> electionVoterList = (List<ElectionVoter>) inputElement;
				ElectionVoter[] electionVoterArray = electionVoterList.toArray(new ElectionVoter[electionVoterList.size()]);
				return electionVoterArray;
			}
		});

		cmpVotersButtons = new Composite(cmpVoters, SWT.NONE);
		GridData gdCmpVotersButtons = new GridData(SWT.FILL, SWT.TOP, false, true, 1, 1);
		gdCmpVotersButtons.widthHint = 160;
		cmpVotersButtons.setLayoutData(gdCmpVotersButtons);
		cmpVotersButtons.setLayout(new FillLayout(SWT.VERTICAL));

		btnVote = new Button(cmpVotersButtons, SWT.NONE);
		btnVote.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				ElectionVoter selectedElectionVoter = getSelectedElectionVoter();
				if (selectedElectionVoter == null) {
					MessageDialog.openInformation(shlMain, "Information", "You must select Voter");
				} else {
					if (selectedElectionVoter.getIsNonResident() == true) {
						electionService.verifyNonresidentVoter(loggedElection, selectedElectionVoter.getVoter().getIdentificationField(), shlMain);
					} else {
						Boolean verificationResult = electionService.verifyVoter(loggedElection, selectedElectionVoter.getVoter().getIdentificationField());
						if (verificationResult == true) {
							MessageDialog.openInformation(shlMain, "Information", "Voter " + selectedElectionVoter.getVoter() + " can proceed to vote.");
							refreshSelectedPage();
						} else {
							MessageDialog.openInformation(shlMain, "Information", "Voter " + selectedElectionVoter.getVoter() + " has already voted.");
						}
					}
				}
			}
		});
		btnVote.setText("Verify");
	}

	private void initMainCmp() {
		mainCmpTxtMember.setText(loggedMember.toString());
		mainCmpTxtElection.setText(loggedElection.getName());

		txtElectionName.setText(loggedElection.getName());
		txtElectionDescription.setText(loggedElection.getDescription());
		txtElectionStartDate.setText(Converter.dateToString(loggedElection.getStartDate()));
		txtElectionEndDate.setText(Converter.dateToString(loggedElection.getEndDate()));

		switch (loggedElection.getStatus()) {
		case UNSTARTED:
			btnStartEndElection.setText("Start Election");
			btnStartEndElection.setEnabled(true);
			break;
		case INPROGRESS:
			btnStartEndElection.setText("End Election");
			btnStartEndElection.setEnabled(true);
			break;
		case COMPLETED:
			btnStartEndElection.setText("End Election");
			btnStartEndElection.setEnabled(false);
			break;
		default:
			break;
		}

		tblVwrVoters.setInput(loggedElection.getVoters());
	}

	private ElectionVoter getSelectedElectionVoter() {
		return (ElectionVoter) ((StructuredSelection) tblVwrVoters.getSelection()).getFirstElement();
	}

	private void refreshSelectedPage() {
		switch (tbFldMain.getSelection()[0].getText()) {
		case "Election":
			break;
		case "Voters":
			tblVwrVoters.setInput(electionService.findElectionVotersLike(loggedElection, txtVoterSearch.getText()));
			break;
		}
	}
}
